package com.link.play.fit.ai.ui.main

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.link.play.fit.ai.bean.BaseByDesFixBean
import com.link.play.fit.ai.bean.BaseFoodInfoBean
import com.link.play.fit.ai.bean.BaseScanFoodBean
import com.link.play.fit.ai.bean.CalControlReqData
import com.link.play.fit.ai.bean.CalendarStatusData
import com.link.play.fit.ai.bean.DesBean
import com.link.play.fit.ai.bean.RecentlyEatenData
import com.link.play.fit.ai.bean.UserGuide
import com.link.play.fit.ai.ext.d
import com.link.play.fit.ai.store.CloudStore
import com.link.play.fit.ai.store.CloudStore.DOC_CALENDAR_STATUS_LIST_DATA_KEY
import com.link.play.fit.ai.utils.ApiResult
import com.link.play.fit.ai.utils.ApiService
import com.link.play.fit.ai.utils.DateEx.getDayOfMonth
import com.link.play.fit.ai.utils.DateEx.getTimeStamp
import com.link.play.fit.ai.utils.EventUtils
import com.link.play.fit.ai.utils.FileUtils.fileToPart
import com.link.play.fit.ai.utils.HttpResponse.safeApiCall
import com.link.play.fit.ai.utils.RetrofitClient
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import org.json.JSONObject
import java.io.File

class MainViewModel : ViewModel() {

    private val apiService = RetrofitClient.createService(ApiService::class.java)
    private val scanJobs = mutableMapOf<String, Job>()
    val recentlyGoalData: StateFlow<UserGuide>
        get() = _recentlyGoalData.asStateFlow()
    private val _recentlyGoalData = MutableStateFlow(UserGuide())
    private var calendarStatusData: MutableStateFlow<CalendarStatusData> =
        MutableStateFlow(CalendarStatusData())

    val foodBeanLiveData: SharedFlow<BaseScanFoodBean> get() = _foodBeanLiveData
    private val _foodBeanLiveData = MutableSharedFlow<BaseScanFoodBean>(replay = 0)

    private val _foodBeanFlow = MutableStateFlow<BaseScanFoodBean?>(null)
    val foodBeanFlow: StateFlow<BaseScanFoodBean?> = _foodBeanFlow.asStateFlow()

    // fooddatabase ai 生成的食物
    var foodInfoLiveData: MutableStateFlow<BaseFoodInfoBean> = MutableStateFlow(BaseFoodInfoBean())
//    var desFixLiveBean: MutableStateFlow<BaseByDesFixBean> = MutableStateFlow(BaseByDesFixBean())
    private val _desFixLiveBean = MutableStateFlow<BaseByDesFixBean?>(null)
    val desFixLiveBean: StateFlow<BaseByDesFixBean?> = _desFixLiveBean.asStateFlow()

    private val _message = MutableLiveData<String>()
    val message: LiveData<String> = _message

    private var mCalendarPosition = 0
    private var timeDay = ""
    private var mDatesList: MutableList<CalendarStatusData> = mutableListOf()

    private val _items = mutableListOf<String>()
    val items: List<String> get() = _items.toList()
    private val _goalPromptList = MutableSharedFlow<List<String>>(replay = 1)
    val goalPromptList: SharedFlow<List<String>> = _goalPromptList

    private val _flushControlLiveData = MutableLiveData<String>()
    val flushControlLiveData: LiveData<String> = _flushControlLiveData

    fun updateFlushControlLiveData(newData: String) {
        _flushControlLiveData.value = newData
    }

    fun addPrompItem(item: String) {
        _items.add(item)
        notifyListUpdate()
    }

    fun clearPrompItem() {
        _items.clear()
        notifyListUpdate()
    }

    private fun notifyListUpdate() {
        viewModelScope.launch {

            _goalPromptList.emit(items)
        }
    }

    fun setDateList(list: MutableList<CalendarStatusData>) {
        mDatesList = list
    }

    fun getDateList(): MutableList<CalendarStatusData> {
        return mDatesList
    }

    fun setTimeDay(time: String) {
        timeDay = time
    }

    fun getTimeDay(): String {
        return timeDay
    }

    fun setCalendarPosition(p: Int) {
        mCalendarPosition = p
    }

    fun getCalendarPosition(): Int {
        return mCalendarPosition
    }

    fun onclickTapScan(newData: String) {
        _message.value = newData
    }

    fun setData(userGuide: UserGuide) {
        _recentlyGoalData.update { userGuide }
    }

    fun setCalendarData(data: CalendarStatusData) {
        calendarStatusData.update { data }
    }

    fun getCalendarData(): CalendarStatusData {
        return calendarStatusData.value
    }


    fun updateGoalData(
        caloriesDaily: Int,
        carbsDaily: Int,
        proteinDaily: Int,
        fatsDaily: Int
    ) {
        _recentlyGoalData.update { currentData ->
            currentData.copy(
                caloriesDaily = caloriesDaily,
                carbsDaily = carbsDaily,
                proteinDaily = proteinDaily,
                fatsDaily = fatsDaily
            )
        }
    }


    fun getGoalData(): UserGuide {
        return _recentlyGoalData.value
    }

    fun saveCalendarListData(data: CalendarStatusData) {
        val today = getDayOfMonth()
        val key = getTimeStamp(today)
        CloudStore.addToList(
            CloudStore.DOC_CALENDAR_STATUS_LIST_DATA,
            date = DOC_CALENDAR_STATUS_LIST_DATA_KEY,
            key = key,
            data = data
        )
    }

    fun putCalendarListData(oldData: CalendarStatusData) {
        CloudStore.addToList(
            CloudStore.DOC_CALENDAR_STATUS_LIST_DATA,
            date = DOC_CALENDAR_STATUS_LIST_DATA_KEY,
            key = getTimeStamp(oldData.timeDate),
            data = oldData
        )
    }


    fun saveRecentlyData(data: RecentlyEatenData) {
        CloudStore.addToList(
            CloudStore.DOC_RECENTLY_LIST_DATA,
            date = data.timeDay,
            key = data.createTime,
            data = data
        )
    }

    /**
     * 扫描食物
     */
    fun scanFood(file: File, timeId: String, bean: RecentlyEatenData) {
        val eventString = StringBuilder("food_scan_food_")
        // 取消相同 timeId 的旧请求（如果存在）
        scanJobs[timeId]?.cancel()

        val newJob = viewModelScope.launch(Dispatchers.IO) {
            when (val result = safeApiCall {
                apiService.scan(fileToPart(file))
            }) {
                is ApiResult.Success -> {
                    _foodBeanFlow.emit(
                        BaseScanFoodBean(
                            status = 200,
                            timeId = timeId,
                            scanFoodBean = result.data,
                            recentlyEatenData = bean
                        )
                    )
                    EventUtils.event(eventString.append("success").toString())
                }

                is ApiResult.BusinessError -> {
                    _foodBeanFlow.emit(
                        BaseScanFoodBean(
                            status = 200,
                            timeId = timeId, msg = result.message,
                            recentlyEatenData = bean
                        )
                    )
                    EventUtils.event(
                        eventString.append("error").toString(),
                        ext = JSONObject().apply {
                            put("info", result.message)
                        })
                }

                is ApiResult.HttpError -> {
                    _foodBeanFlow.emit(
                        BaseScanFoodBean(
                            status = 200,
                            timeId = timeId, msg = result.message,
                            recentlyEatenData = bean
                        )
                    )
                    EventUtils.event(
                        eventString.append("error").toString(),
                        ext = JSONObject().apply {
                            put("info", result.message)
                        })
                }

                is ApiResult.NetworkError -> {
                    _foodBeanFlow.emit(
                        BaseScanFoodBean(
                            status = 200,
                            timeId = timeId, msg = "Network connection failed",
                            recentlyEatenData = bean
                        )
                    )
                    EventUtils.event(
                        eventString.append("error").toString(),
                        ext = JSONObject().apply {
                            put("info", "NetworkError")
                        })
                }
            }
            scanJobs.remove(timeId)
        }
        scanJobs[timeId] = newJob
    }

    /**
     * 扫描商品码
     */
    fun barcode(file: File, timeId: String, bean: RecentlyEatenData) {
        val eventString = StringBuilder("food_scan_bar_")
        viewModelScope.launch {
            when (val result = safeApiCall {
                apiService.barcode(fileToPart(file))
            }) {
                is ApiResult.Success -> {
                    _foodBeanFlow.emit(
                        BaseScanFoodBean(
                            status = 200,
                            timeId = timeId,
                            scanFoodBean = result.data,
                            recentlyEatenData = bean
                        )
                    )
                    EventUtils.event(eventString.append("success").toString())
                }

                is ApiResult.BusinessError -> {
                    _foodBeanFlow.emit(
                        BaseScanFoodBean(
                            status = 200,
                            timeId = timeId,
                            msg = result.message,
                            recentlyEatenData = bean
                        )
                    )
                    EventUtils.event(
                        eventString.append("error").toString(),
                        ext = JSONObject().apply {
                            put("info", result.message)
                        })
                }

                is ApiResult.HttpError -> {
                    _foodBeanFlow.emit(
                        BaseScanFoodBean(
                            status = 200,
                            timeId = timeId,
                            msg = result.message,
                            recentlyEatenData = bean
                        )
                    )
                    EventUtils.event(
                        eventString.append("error").toString(),
                        ext = JSONObject().apply {
                            put("info", result.message)
                        })
                }

                is ApiResult.NetworkError -> {
                    _foodBeanFlow.emit(
                        BaseScanFoodBean(
                            status = 200,
                            timeId = timeId,
                            msg = "Network connection failed",
                            recentlyEatenData = bean
                        )
                    )
                    EventUtils.event(
                        eventString.append("error").toString(),
                        ext = JSONObject().apply {
                            put("info", "NetworkError")
                        })
                }
            }
        }
    }

    /**
     * 根据食物标签获取
     */
    fun label(file: File, timeId: String, bean: RecentlyEatenData) {
        val eventString = StringBuilder("food_scan_label_")
        viewModelScope.launch {
            when (val result = safeApiCall {
                apiService.label(fileToPart(file))
            }) {
                is ApiResult.Success -> {
                    _foodBeanFlow.emit(
                        BaseScanFoodBean(
                            status = 200,
                            timeId = timeId,
                            scanFoodBean = result.data,
                            recentlyEatenData = bean
                        )
                    )
                    EventUtils.event(
                        eventString.append("success").toString()
                    )
                }

                is ApiResult.BusinessError -> {
                    _foodBeanFlow.emit(
                        BaseScanFoodBean(
                            status = 200,
                            timeId = timeId,
                            msg = result.message,
                            recentlyEatenData = bean
                        )
                    )

                    EventUtils.event(
                        eventString.append("error").toString(),
                        ext = JSONObject().apply {
                            put("info", result.message)
                        })
                }

                is ApiResult.HttpError -> {
                    _foodBeanFlow.emit(
                        BaseScanFoodBean(
                            status = 200,
                            timeId = timeId,
                            msg = result.message,
                            recentlyEatenData = bean
                        )
                    )
                    EventUtils.event(
                        eventString.append("error").toString(),
                        ext = JSONObject().apply {
                            put("info", result.message)
                        })
                }

                is ApiResult.NetworkError -> {
                    _foodBeanFlow.emit(
                        BaseScanFoodBean(
                            status = 200,
                            timeId = timeId,
                            msg = "Network connection failed",
                            recentlyEatenData = bean
                        )
                    )
                    EventUtils.event(
                        eventString.append("error").toString(),
                        ext = JSONObject().apply {
                            put("info", "NetworkError")
                        })

                }
            }
        }
    }

    /**
     * 根据名字返回cal
     */
    fun getFoodInfo(name: String, timeId: String, bean: RecentlyEatenData) {
        viewModelScope.launch {
            when (val result = safeApiCall {
                apiService.getFoodInfo(name)
            }) {
                is ApiResult.Success -> {
//                (foodBeanLiveData as MutableLiveData).postValue( result)
                    foodInfoLiveData.update {
                        it.copy(
                            status = 200,
                            timeId = timeId,
                            foodInfo = result.data,
                            recentlyEatenData = bean
                        )
                    }
                }

                is ApiResult.BusinessError -> {
                    foodInfoLiveData.update {
                        it.copy(
                            status = result.status,
                            msg = result.message,
                            timeId = timeId,
                            recentlyEatenData = bean
                        )
                    }
                }

                is ApiResult.HttpError -> {
                    foodInfoLiveData.update {
                        it.copy(
                            status = result.code,
                            msg = result.message,
                            timeId = timeId,
                            recentlyEatenData = bean
                        )
                    }
                }

                is ApiResult.NetworkError -> {
                    foodInfoLiveData.update {
                        it.copy(
                            status = 400,
                            msg = "Network connection failed",
                            timeId = timeId,
                            recentlyEatenData = bean
                        )
                    }
                }
            }
        }
    }

    /**
     * Ai根据名字返回cal
     */
    fun getAiFoodInfo(name: String, timeId: String, bean: RecentlyEatenData) {
        viewModelScope.launch {
            when (val result = safeApiCall {
                apiService.getFoodInfoAi(name)
            }) {
                is ApiResult.Success -> {
                    foodInfoLiveData.update {
                        it.copy(
                            status = 200,
                            timeId = timeId,
                            aiFoodInfo = result.data,
                            recentlyEatenData = bean
                        )
                    }
                }

                is ApiResult.BusinessError -> {
                    foodInfoLiveData.update {
                        it.copy(
                            status = result.status,
                            msg = result.message,
                            timeId = timeId,
                            recentlyEatenData = bean
                        )
                    }
                }

                is ApiResult.HttpError -> {
                    foodInfoLiveData.update {
                        it.copy(
                            status = result.code,
                            msg = result.message,
                            timeId = timeId,
                            recentlyEatenData = bean
                        )
                    }
                }

                is ApiResult.NetworkError -> {
                    foodInfoLiveData.update {
                        it.copy(
                            status = 400,
                            msg = "Network connection failed",
                            timeId = timeId,
                            recentlyEatenData = bean
                        )
                    }
                }
            }
        }
    }

    /**
     * 根据描述修正
     */
    fun byDescribe(data: DesBean, timeId: String) {
        "============== byDescribe ============== $data".d()
        viewModelScope.launch {
            when (val result = safeApiCall {
                apiService.byExerciseDescribe(data)
            }) {
                is ApiResult.Success -> {
//                    _desFixLiveBean.update {
//                        it?.copy(status = 200, byDesFixBean = result.data, timeId = timeId)
//                    }
                    _desFixLiveBean.emit(
                        BaseByDesFixBean(
                            status = 200, byDesFixBean = result.data, timeId = timeId
                        )
                    )
                }

                is ApiResult.BusinessError -> {
//                    _desFixLiveBean.update {
//                        it?.copy(status = result.status, msg = result.message)
//                    }
                    _desFixLiveBean.emit(
                        BaseByDesFixBean(
                            status = result.status, msg = result.message
                        )
                    )
                }

                is ApiResult.HttpError -> {
                    _desFixLiveBean.emit(
                        BaseByDesFixBean(
                            status = result.code, msg = result.message
                        )
                    )
                }

                is ApiResult.NetworkError -> {
                    _desFixLiveBean.emit(
                        BaseByDesFixBean(
                            status = 400, msg = "Network connection failed"
                        )
                    )
                }
            }
        }
    }


    /**
     * AI减肥饮食运动计划接口
     */
    fun getCalControl(data: CalControlReqData) {
        "=========getCalControl  $data".d()
        if(data.cycle.toInt() == -1) {
            "数据异常 data.cycle ${data.cycle}".d()
            return
        }
        viewModelScope.launch {
            when (val result = safeApiCall {
                apiService.calControl(data)
            }) {
                is ApiResult.Success -> {
                    _foodBeanLiveData.emit(
                        BaseScanFoodBean(
                            status = 200,
                            calControlData = result.data
                        )
                    )
                }

                is ApiResult.BusinessError -> {
                    _foodBeanLiveData.emit(
                        BaseScanFoodBean(
                            status = 200,
                        )
                    )
                }

                is ApiResult.HttpError -> {
                    _foodBeanLiveData.emit(
                        BaseScanFoodBean(
                            status = 200,
                        )
                    )
                }

                is ApiResult.NetworkError -> {
                    _foodBeanLiveData.emit(
                        BaseScanFoodBean(
                            status = 200,
                        )
                    )
                }
            }
        }
    }


}